import configparser,os,sys,time,datetime
from tkinter import *
from tkinter.ttk import *
class WinGUI(Tk):
    def __init__(self):
        super().__init__()
        self.__win()
        self.tk_label_frame_23 = self.__tk_label_frame_23(self)
        self.tk_label_DMA路径标签 = self.__tk_label_DMA路径标签( self.tk_label_frame_23)
        self.tk_button_扫单保存 = self.__tk_button_扫单保存( self.tk_label_frame_23)
        self.tk_label_运行日期标签 = self.__tk_label_运行日期标签( self.tk_label_frame_23)
        self.tk_input_开始日期输入 = self.__tk_input_开始日期输入( self.tk_label_frame_23)
        self.tk_label_lpnj2d7c = self.__tk_label_lpnj2d7c( self.tk_label_frame_23)
        self.tk_label_账号密码标签 = self.__tk_label_账号密码标签( self.tk_label_frame_23)
        self.tk_input_结束日期输入 = self.__tk_input_结束日期输入( self.tk_label_frame_23)
        self.tk_input_OQ账号输入 = self.__tk_input_OQ账号输入( self.tk_label_frame_23)
        self.tk_input_OQ密码输入 = self.__tk_input_OQ密码输入( self.tk_label_frame_23)
        self.tk_input_DMA路径输入 = self.__tk_input_DMA路径输入( self.tk_label_frame_23)
        self.tk_label_ALGO路径标签 = self.__tk_label_ALGO路径标签( self.tk_label_frame_23)
        self.tk_input_ALGO路径输入 = self.__tk_input_ALGO路径输入( self.tk_label_frame_23)
        self.tk_label_frame_lpnj38ck = self.__tk_label_frame_lpnj38ck(self)
        self.tk_label_开始时间标签 = self.__tk_label_开始时间标签( self.tk_label_frame_lpnj38ck)
        self.tk_input_下单开始时间输入 = self.__tk_input_下单开始时间输入( self.tk_label_frame_lpnj38ck)
        self.tk_label_结束时间标签 = self.__tk_label_结束时间标签( self.tk_label_frame_lpnj38ck)
        self.tk_input_下单结束时间输入 = self.__tk_input_下单结束时间输入( self.tk_label_frame_lpnj38ck)
        self.tk_label_下单间隔标签 = self.__tk_label_下单间隔标签( self.tk_label_frame_lpnj38ck)
        self.tk_label_下单发单量标签 = self.__tk_label_下单发单量标签( self.tk_label_frame_lpnj38ck)
        self.tk_input_下单发单量输入 = self.__tk_input_下单发单量输入( self.tk_label_frame_lpnj38ck)
        self.tk_label_撤单间隔标签 = self.__tk_label_撤单间隔标签( self.tk_label_frame_lpnj38ck)
        self.tk_input_下单间隔输入 = self.__tk_input_下单间隔输入( self.tk_label_frame_lpnj38ck)
        self.tk_input_撤单间隔输入 = self.__tk_input_撤单间隔输入( self.tk_label_frame_lpnj38ck)
        self.tk_input_撤单发单量输入 = self.__tk_input_撤单发单量输入( self.tk_label_frame_lpnj38ck)
        self.tk_button_下单设置保存 = self.__tk_button_下单设置保存( self.tk_label_frame_lpnj38ck)
        self.tk_label_起始批号标签 = self.__tk_label_起始批号标签( self.tk_label_frame_lpnj38ck)
        self.tk_label_结束批号标签 = self.__tk_label_结束批号标签( self.tk_label_frame_lpnj38ck)
        self.tk_input_起始批号输入 = self.__tk_input_起始批号输入( self.tk_label_frame_lpnj38ck)
        self.tk_input_结束批号输入 = self.__tk_input_结束批号输入( self.tk_label_frame_lpnj38ck)
        self.tk_label_撤单发单量标签 = self.__tk_label_撤单发单量标签(self)
        self.tk_button_运行策略 = self.__tk_button_运行策略(self)
        self.tk_label_frame_lpnja29w = self.__tk_label_frame_lpnja29w(self)
        self.tk_label_指令内容标签 = self.__tk_label_指令内容标签( self.tk_label_frame_lpnja29w)
        self.tk_button_追加按钮 = self.__tk_button_追加按钮( self.tk_label_frame_lpnja29w)
        self.tk_text_追加指令内容 = self.__tk_text_追加指令内容( self.tk_label_frame_lpnja29w)
    def __win(self):
        self.title("OQ文件单助手")
        # 设置窗口大小、居中
        width = 800
        height = 530
        screenwidth = self.winfo_screenwidth()
        screenheight = self.winfo_screenheight()
        geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        self.geometry(geometry)

        self.resizable(width=False, height=False)

    def scrollbar_autohide(self,vbar, hbar, widget):
        """自动隐藏滚动条"""
        def show():
            if vbar: vbar.lift(widget)
            if hbar: hbar.lift(widget)
        def hide():
            if vbar: vbar.lower(widget)
            if hbar: hbar.lower(widget)
        hide()
        widget.bind("<Enter>", lambda e: show())
        if vbar: vbar.bind("<Enter>", lambda e: show())
        if vbar: vbar.bind("<Leave>", lambda e: hide())
        if hbar: hbar.bind("<Enter>", lambda e: show())
        if hbar: hbar.bind("<Leave>", lambda e: hide())
        widget.bind("<Leave>", lambda e: hide())

    def v_scrollbar(self,vbar, widget, x, y, w, h, pw, ph):
        widget.configure(yscrollcommand=vbar.set)
        vbar.config(command=widget.yview)
        vbar.place(relx=(w + x) / pw, rely=y / ph, relheight=h / ph, anchor='ne')
    def h_scrollbar(self,hbar, widget, x, y, w, h, pw, ph):
        widget.configure(xscrollcommand=hbar.set)
        hbar.config(command=widget.xview)
        hbar.place(relx=x / pw, rely=(y + h) / ph, relwidth=w / pw, anchor='sw')
    def create_bar(self,master, widget,is_vbar,is_hbar, x, y, w, h, pw, ph):
        vbar, hbar = None, None
        if is_vbar:
            vbar = Scrollbar(master)
            self.v_scrollbar(vbar, widget, x, y, w, h, pw, ph)
        if is_hbar:
            hbar = Scrollbar(master, orient="horizontal")
            self.h_scrollbar(hbar, widget, x, y, w, h, pw, ph)
        self.scrollbar_autohide(vbar, hbar, widget)
    def __tk_label_frame_23(self,parent):
        frame = LabelFrame(parent,text="扫单设置",)
        frame.place(x=20, y=3, width=736, height=157)
        return frame
    def __tk_label_DMA路径标签(self,parent):
        label = Label(parent,text="DMA路径：",anchor="center", )
        label.place(x=10, y=5, width=66, height=30)
        return label
    def __tk_button_扫单保存(self,parent):
        btn = Button(parent, text="保存", takefocus=False,)
        btn.place(x=679, y=0, width=50, height=30)
        return btn
    def __tk_label_运行日期标签(self,parent):
        label = Label(parent,text="运行日期：",anchor="center", )
        label.place(x=10, y=88, width=67, height=30)
        return label

    # 加载config配置项并显示到输入框组件
    def load_config(self,组件,配置项):
        config = configparser.ConfigParser()
        配置文件目录=os.path.dirname(os.path.realpath(sys.argv[0]))
        config.read(os.path.join(配置文件目录,'scanConfig.ini'),encoding='utf-8')   # 读取config.ini
        配置内容=config.get("scan", 配置项)
        if 配置项 in["beginDate","endDate"] and 配置内容=="":
            组件.insert(0, "")
        else:
            组件.insert(0, 配置内容)


    # 修改config配置项并显示到输入框组件
    def update_cfg_ini(self,params,path_filename):
        # params = self.load_config(self.configfile)
        params.set("Params", "MarketPosition", str(self.MarketPosition[合约代码]))
        params.set("Params", "pos", str(self.pos[合约代码]))
        with open(path_filename, 'w',encoding='utf-8') as configfile:
            params.write(configfile)

    def __tk_input_开始日期输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"beginDate")
        ipt.place(x=80, y=88, width=99, height=30)
        return ipt
    def __tk_label_lpnj2d7c(self,parent):
        label = Label(parent,text="至",anchor="center", )
        label.place(x=185, y=88, width=37, height=30)
        return label
    def __tk_label_账号密码标签(self,parent):
        label = Label(parent,text="账号密码：",anchor="center", )
        label.place(x=346, y=89, width=62, height=30)
        return label
    def __tk_input_结束日期输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"endDate")
        ipt.place(x=230, y=88, width=99, height=30)
        return ipt
    def __tk_input_OQ账号输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"OQAcct")
        ipt.place(x=412, y=89, width=99, height=30)
        return ipt
    def __tk_input_OQ密码输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"OQCode")
        ipt.place(x=540, y=89, width=99, height=30)
        return ipt
    def __tk_input_DMA路径输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"DMADir")
        ipt.place(x=80, y=5, width=560, height=30)
        return ipt
    def __tk_label_ALGO路径标签(self,parent):
        label = Label(parent,text="ALGO路径:",anchor="center", )
        label.place(x=10, y=46, width=66, height=30)
        return label
    def __tk_input_ALGO路径输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"algoDir")
        ipt.place(x=80, y=45, width=561, height=30)
        return ipt
    def __tk_label_frame_lpnj38ck(self,parent):
        frame = LabelFrame(parent,text="下单设置",)
        frame.place(x=20, y=174, width=731, height=151)
        return frame
    def __tk_label_开始时间标签(self,parent):
        label = Label(parent,text="开始时间：",anchor="center", )
        label.place(x=10, y=10, width=62, height=30)
        return label
    def __tk_input_下单开始时间输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"beginTime")
        ipt.place(x=72, y=10, width=107, height=30)
        return ipt
    def __tk_label_结束时间标签(self,parent):
        label = Label(parent,text="结束时间：",anchor="center", )
        label.place(x=260, y=10, width=63, height=30)
        return label
    def __tk_input_下单结束时间输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"endTime")
        ipt.place(x=340, y=10, width=107, height=30)
        return ipt
    def __tk_label_下单间隔标签(self,parent):
        label = Label(parent,text="下单间隔：",anchor="center", )
        label.place(x=10, y=50, width=61, height=30)
        return label
    def __tk_label_下单发单量标签(self,parent):
        label = Label(parent,text="下单发单量：",anchor="center", )
        label.place(x=260, y=50, width=76, height=30)
        return label
    def __tk_input_下单发单量输入(self,parent):
        ipt = Entry(parent, )

        self.load_config(ipt,"orderSleep")
        ipt.place(x=340, y=50, width=107, height=30)
        return ipt
    def __tk_label_撤单间隔标签(self,parent):
        label = Label(parent,text="撤单间隔：",anchor="center", )
        label.place(x=10, y=90, width=62, height=30)
        return label
    def __tk_input_下单间隔输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"orderTime")
        ipt.place(x=72, y=50, width=107, height=30)
        return ipt
    def __tk_input_撤单间隔输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"cancelSleep")
        ipt.place(x=73, y=90, width=107, height=30)
        return ipt
    def __tk_input_撤单发单量输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"cancelTime")
        ipt.place(x=340, y=90, width=107, height=30)
        return ipt
    def __tk_button_下单设置保存(self,parent):
        btn = Button(parent, text="保存", takefocus=False,)
        btn.place(x=680, y=0, width=50, height=30)
        return btn
    def __tk_label_起始批号标签(self,parent):
        label = Label(parent,text="起始批号：",anchor="center", )
        label.place(x=480, y=10, width=63, height=30)
        return label
    def __tk_label_结束批号标签(self,parent):
        label = Label(parent,text="结束批号：",anchor="center", )
        label.place(x=480, y=50, width=63, height=30)
        return label
    def __tk_input_起始批号输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"beginBatchNo")
        ipt.place(x=545, y=10, width=107, height=30)
        return ipt
    def __tk_input_结束批号输入(self,parent):
        ipt = Entry(parent, )
        self.load_config(ipt,"endBatchNo")
        ipt.place(x=547, y=50, width=107, height=30)
        return ipt
    def __tk_label_撤单发单量标签(self,parent):
        label = Label(parent,text="撤单发单量：",anchor="center", )
        label.place(x=282, y=283, width=78, height=30)
        return label
    def __tk_button_运行策略(self,parent):
        btn = Button(parent, text="运行策略", takefocus=False,)
        btn.place(x=630, y=342, width=126, height=30)
        return btn
    def __tk_label_frame_lpnja29w(self,parent):
        frame = LabelFrame(parent,text="追加指令",)
        frame.place(x=21, y=376, width=736, height=126)
        return frame
    def __tk_label_指令内容标签(self,parent):
        label = Label(parent,text="指令内容：",anchor="center", )
        label.place(x=10, y=3, width=62, height=30)
        return label
    def __tk_button_追加按钮(self,parent):
        btn = Button(parent, text="追加", takefocus=False,)
        btn.place(x=677, y=70, width=50, height=30)
        return btn
    def __tk_text_追加指令内容(self,parent):
        text = Text(parent)
        text.place(x=70, y=0, width=583, height=89)
        return text
class Win(WinGUI):
    def __init__(self):
        super().__init__()
        self.__event_bind()

    # 修改config配置项并显示到输入框组件
    def update_cfg_ini(self,配置项,新配置内容):
        config = configparser.ConfigParser()
        配置文件目录=os.path.dirname(os.path.realpath(sys.argv[0]))
        config.read(os.path.join(配置文件目录,'scanConfig.ini'),encoding='utf-8')   # 读取config.ini
        config.set("scan", 配置项, 新配置内容)
        with open(os.path.join(配置文件目录,'scanConfig.ini'), 'w',encoding='utf-8') as configfile:
            config.write(configfile)


    def 保存路径(self,evt):
        新DMA路径=self.tk_input_DMA路径输入.get()
        新ALGO路径=self.tk_input_ALGO路径输入.get()
        新开始日期=self.tk_input_开始日期输入.get()
        新结束日期=self.tk_input_结束日期输入.get()
        新OQ密码=self.tk_input_OQ密码输入.get()
        新OQ账号=self.tk_input_OQ账号输入.get()
        self.update_cfg_ini("DMADir",新DMA路径)
        self.update_cfg_ini("algoDir",新ALGO路径)
        self.update_cfg_ini("beginDate",新开始日期)
        self.update_cfg_ini("endDate",新结束日期)
        self.update_cfg_ini("OQAcct",新OQ账号)
        self.update_cfg_ini("OQCode",新OQ密码)
        print("扫单参数设置已保存")
    def 保存下单设置(self,evt):
        self.新下单开始时间=self.tk_input_下单开始时间输入.get()
        self.新下单结束时间=self.tk_input_下单结束时间输入.get()
        self.新起始批号=self.tk_input_起始批号输入.get()
        self.新结束批号=self.tk_input_结束批号输入.get()
        self.新下单间隔=self.tk_input_下单间隔输入.get()
        self.新下单发单量=self.tk_input_下单发单量输入.get()
        self.新撤单间隔=self.tk_input_撤单间隔输入.get()
        self.新撤单发单量=self.tk_input_撤单发单量输入.get()
        self.update_cfg_ini("begintime",新下单开始时间)
        self.update_cfg_ini("endtime",新下单结束时间)
        self.update_cfg_ini("beginbatchno",新起始批号)
        self.update_cfg_ini("endbatchno",新结束批号)
        self.update_cfg_ini("ordersleep",新下单间隔)
        self.update_cfg_ini("ordertime",新下单发单量)
        self.update_cfg_ini("cancelsleep",新撤单间隔)
        self.update_cfg_ini("canceltime",新撤单发单量)
        print("下单参数设置已保存")
    def 运行策略(self,evt):
        start_time = datetime.time(int(self.tk_input_下单开始时间输入.get()[0:2]), int(self.tk_input_下单开始时间输入.get()[2:4]))
        end_time = datetime.time(int(self.tk_input_下单结束时间输入.get()[0:2]), int(self.tk_input_下单结束时间输入.get()[2:4]))
        current_time = datetime.datetime.now().time()
        if start_time <= current_time <= end_time:
            print("达到开始时间，开始运行策略")
        print("<Double-Button-1>事件未处理:",evt)
    def 追加指令(self,evt):
        print("<Double-Button-1>事件未处理:",evt)
    def __event_bind(self):
        self.tk_button_扫单保存.bind('<Double-Button-1>',self.保存路径)
        self.tk_button_下单设置保存.bind('<Double-Button-1>',self.保存下单设置)
        self.tk_button_运行策略.bind('<Double-Button-1>',self.运行策略)
        self.tk_button_追加按钮.bind('<Double-Button-1>',self.追加指令)
        pass

# 自动登录OQ
def logOnOneQuant(exeFile,OQ登录密码):
    autoLogOnOneQuant = """
        set wshell=createobject("wscript.shell")
        wshell.run "__oneQuantExeFile__",1
        wscript.sleep 3500
        Dim count:count=100
        Do While wshell.AppActivate("安信OneQuant")<> true
            wscript.sleep 200
            count = count-1
            If count=0 Then
                msgbox "启动失败",,"oneQuant提示"
                wscript.quit
                Exit Do
            End If
        Loop
        wscript.sleep 500
        wshell.sendkeys "{TAB}"
        wshell.sendkeys "__oneQuant密码__"
        wshell.sendkeys "{enter}"
        wscript.sleep 1000
        
        """

    if os.path.exists(exeFile) and OQ登录密码 :
        script=autoLogOnOneQuant.replace("__oneQuantExeFile__",exeFile).replace("__oneQuant密码__",OQ登录密码)
        tmpfile = "./tmplogOnoq.vbs"
        with open(tmpfile,'w') as f:
            f.write(script)
        status = os.system("taskkill /im  AxOneQuant.exe /T /F")
        if status==0:
            print("终止AxOneQuant.exe成功")
        else:
            print("终止AxOneQuant.exe失败")
        time.sleep(1)
        os.system("start %s" % tmpfile)
        time.sleep(2)
        os.remove(tmpfile)

def order_dma(fd,dmaOrder:DMAOrder):

    dma_order_str=dmaOrder.toCSVFormat()
    fd.write(dma_order_str+"\n")   # 写入DMA文件
    printLog("写入报单文件:[%-5s]:股票:%s,价格:%s,数量:%d,上浮ticks:%d" % ( TradeSide(dmaOrder.tradeSide).name,dmaOrder.symbol,PriceType(dmaOrder.priceType).name,dmaOrder.targetQty,dmaOrder.ticks),flush = True)

def cancel_dma(fd,order:DMAOrder):

    updTime=datetime.datetime.now().strftime("%Y-%m-%d %H%M%S.%f")[11:-3]   # hhmmss.sss
    cancel_dma_str="%s,%s" % (updTime,order.custBatchNo)
    fd.write(cancel_dma_str+"\n")      # 写入撤单文件
    printLog('写入撤单文件:' + cancel_dma_str,flush = True)

def init_order_cancel_files(order_file,cancel_file):
    if not os.path.exists(order_file):
        with open(order_file,'w') as f:
            f.write("updTime,custBatchNo,acctType,acct,symbol,tradeSide,targetQty,algoId,priceType,ticks,highLimitPrice,lowLimitPrice" + "\n")
        printLog('创建DMA下单文件:' + order_file)
    if not os.path.exists(cancel_file):
        with open(cancel_file,'w') as f:
            f.write("updTime,custBatchNo" + "\n")
        printLog('创建DMA撤单文件:' + cancel_file)
if __name__ == "__main__":


    # 自动登录OQ
    config = configparser.ConfigParser()
    配置文件目录=os.path.dirname(os.path.realpath(sys.argv[0]))
    config.read(os.path.join(配置文件目录,'scanConfig.ini'),encoding='utf-8')   # 读取config.ini
    dma路径=config.get("scan", "dmadir")
    OQ路径=os.path.join(os.path.dirname(os.path.dirname(dma路径)),"AxOneQuant.exe")
    OQ密码=config.get("scan", "oqcode")
    logOnOneQuant(OQ路径,OQ密码)
    time.sleep(5)

    win = Win()
    win.mainloop()
